
package com.shop.cloud.mall.admin.util;

import cn.hutool.core.util.StrUtil;
import com.shop.cloud.common.data.tenant.TenantContextHolder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;

/**
 * 在线用户统计工具类
 * 参考：https://www.jb51.net/article/210809.htm
 * @author
 * @date 2022-06-02 14:20:02
 */
@Component
public class UserOnlineUtil {
	private static final String ONLINE_USERS = "online_users";

	@Resource
	private RedisTemplate redisTemplate;

	/**
	 * 获取一定时间内，在线的用户数量
	 * @param clientType 用户端
	 * @param duration
	 * @return
	 */
	public Long count(String clientType, Duration duration) {
		LocalDateTime now = LocalDateTime.now();
		String key = StrUtil.format("{}:{}:{}", TenantContextHolder.getTenantId(), ONLINE_USERS, clientType);
		return this.redisTemplate.opsForZSet().count(key,
				now.minus(duration).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(),
				now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
	}

	/**
	 * 获取所有在线过的用户数量，不论时间
	 * @param clientType 用户端
	 * @return
	 */
	public Long count(String clientType) {
		String key = StrUtil.format("{}:{}:{}", TenantContextHolder.getTenantId(), ONLINE_USERS, clientType);
		return this.redisTemplate.opsForZSet().zCard(key);
	}

	/**
	 * 清除超过一定时间没在线的用户数据
	 * @param duration
	 * @return
	 */
	public Long clear(Duration duration) {
		String key = StrUtil.format("{}:{}", TenantContextHolder.getTenantId(), ONLINE_USERS);
		return this.redisTemplate.opsForZSet().removeRangeByScore(key, 0,
				LocalDateTime.now().minus(duration).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
	}

	/**
	 * 获取指定userId的score
	 * @param clientType
	 * @param userId
	 * @return
	 */
	public Double getScore(String clientType, String userId) {
		String key = StrUtil.format("{}:{}:{}", TenantContextHolder.getTenantId(), ONLINE_USERS, clientType);
		return this.redisTemplate.opsForZSet().score(key, userId);
	}
}
